<?php
declare(strict_types=1);

namespace App\Common\Modular\System\Serve;

use App\Common\Modular\System\Annotation\Seo;
use App\Common\Modular\System\Model\SeoModel;
use Core\Basics\BasicsServe;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\AnnotationCollector;
use JetBrains\PhpStorm\ArrayShape;

/**
 * SEO服务
 */
class SeoServe extends BasicsServe
{
    const DEFAULT_APP = 'app';

    /**
     * 默认SEO规则,减少文件IO的操作
     * @var array|null
     */
    private ?array $_defaultRule = null;

    /**
     * @return SeoModel::class
     */
    public static function model(): string
    {
        return SeoModel::class;
    }


    /**
     * 获取SEO注解配置
     * @return array
     */
    public function getSeoAnnotation(): array
    {
        $seoList = [];
        $annotationList = AnnotationCollector::list();//全部注解
        foreach ($annotationList as $item) {
            if (!isset($item['_m'])) continue;
            foreach ($item['_m'] as $row) {
                foreach ($row as $info) {
                    if (!($info instanceof Seo && $info->disable === false)) {
                        continue;
                    }
                    $seoList[$info->app][] = ['app' => $info->app, 'name' => $info->name, 'dynamic' => $info->dynamic, 'param' => $info->param, 'sign' => $info->sign, 'callback' => $info->callback];
                }
            }
        }
        return $seoList;
    }


    /**
     * 获取方法SEO注解
     * @param string $method
     * @return array|null
     */
    public function getMethodSeoAnnotation(string $method): ?array
    {
        foreach ($this->getSeoAnnotation() as $group) {
            foreach ($group as $item) {
                if ($method === implode('::', $item['callback'])) {
                    return $item;
                }
            }
        }
        return [];
    }

    /**
     * 获取默认SEO规则
     */
    #[ArrayShape(['title' => 'string', 'keywords' => 'string', 'description' => 'string'])]
    public function getDefaultRule(): array
    {
        if (is_null($this->_defaultRule)) {
            $def = caching()->get('default_rule', ['title' => '', 'keywords' => '', 'description' => '']);
            $this->_defaultRule = ['title' => $def['title'] ?? '', 'keywords' => $def['keywords'] ?? '', 'description' => $def['description'] ?? ''];
        }
        return $this->_defaultRule;
    }


    /**
     * 设置默认SEO规则
     */
    public function setDefaultRule(string $title, string $keywords, string $description): bool
    {
        $this->_defaultRule = ['title' => $title, 'keywords' => $keywords, 'description' => $description];
        return caching()->set('default_rule', $this->_defaultRule);
    }


    /**
     * 导入SEO配置
     * @param bool $clearInvalid 是否删除已失效的规则
     * @return bool
     */
    public function importSeoAnnotation(bool $clearInvalid = false): bool
    {
        Db::beginTransaction();
        $batch = date("dHis");
        foreach ($this->getSeoAnnotation() as $group) {
            foreach ($group as $item) {
                $seo = SeoModel::where(['sign' => $item['sign']])->first();
                if (!$seo) {
                    $seo = new SeoModel();
                    $seo->sign = $item['sign'];
                }
                $seo->batch = $batch;
                $seo->app = $item['app'];
                $seo->name = $item['name'];
                $seo->dynamic = (int)$item['dynamic'];
                $seo->param = $item['param'];
                $seo->updated_at = time();
                if (!$seo->save()) {
                    Db::rollBack();
                    return false;
                }
            }
        }
        if ($clearInvalid === true) {
            SeoModel::whereRaw("`batch`!=?", [$batch])->delete();
        }
        Db::commit();
        return true;
    }
}